﻿using Microsoft.Win32;
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace PP.PaintLib
{

    public class PPWin32
    {
        /// <summary>
        /// 快捷键
        /// </summary>
        public static class HotKey
        {
            //如果函数执行成功，返回值不为0。
            //如果函数执行失败，返回值为0。要得到扩展错误信息，调用GetLastError。
            [DllImport("user32.dll", SetLastError = true)]
            public static extern bool RegisterHotKey(
              IntPtr hWnd,        //要定义热键的窗口的句柄
              int id,           //定义热键ID（不能与其它ID重复）      
              KeyModifiers fsModifiers,  //标识热键是否在按Alt、Ctrl、Shift、Windows等键时才会生效
              Keys vk           //定义热键的内容
              );
            [DllImport("user32.dll", SetLastError = true)]
            public static extern bool UnregisterHotKey(
              IntPtr hWnd,        //要取消热键的窗口的句柄
              int id           //要取消热键的ID
              );

            //定义了辅助键的名称（将数字转变为字符以便于记忆，也可去除此枚举而直接使用数值）
            [Flags()]
            public enum KeyModifiers
            {
                None = 0,
                Alt = 1,
                Ctrl = 2,
                Shift = 4,
                WindowsKey = 8
            }
        }


        #region 公开方法

        /// <summary>
        /// 获取句柄
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern IntPtr WindowFromPoint(Point p);

        /// <summary>
        /// 获取当前鼠标坐标点的像素色
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public static Color GetPixelColor(Point p)
        {
            IntPtr hdc = GetDC(IntPtr.Zero);
            uint pixel = GetPixel(hdc, p.X, p.Y);

            int retCode = ReleaseDC(IntPtr.Zero, hdc);
            if (retCode != 1)
            {
                throw new Exception($"未能释放句柄：{hdc}");
            }

            Color color = Color.FromArgb((int)(pixel & 0x000000FF),
                                         (int)(pixel & 0x0000FF00) >> 8,
                                         (int)(pixel & 0x00FF0000) >> 16);
            return color;
        }

        /// <summary>
        /// 将鼠标移动到指定的屏幕坐标位置
        /// </summary>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern bool SetCursorPos(int X, int Y);

        /// <summary>
        /// 设置桌面壁纸
        /// </summary>
        /// <param name="imagePath">图片路径</param>
        /// <param name="wallpaperStyle">壁纸样式:Fill（填充）; Fit（适应）; Span（跨屏）; Stretch（拉伸）</param>
        /// <param name="isTile">平铺壁纸属性:True（是）; False（否）</param>
        public static void SetDeskWallPaper(string imagePath, string wallpaperStyle = "Fill", bool isTile = false)
        {
            SetWallpaper(imagePath);
            SetWallpaperStyle(wallpaperStyle);
            SetTileWallpaper(isTile);
        }

        /// <summary>
        /// 获取桌面壁纸文件路径
        /// </summary>
        /// <returns></returns>
        public static string GetWallpaperPath()
        {
            string wallpaperStr = new string('\0', 260);
            SystemParametersInfo(SPI_GETDESKWALLPAPER, 260, wallpaperStr, 0);
            return wallpaperStr.Substring(0, wallpaperStr.IndexOf('\0'));
        }

        /// <summary>
        /// 获取鼠标坐标
        /// </summary>
        public static Point GetMousePosition()
        {
            Point mp = new Point();
            GetCursorPos(out mp);
            return mp;
        }

        #endregion

        private const int SPI_SETDESKWALLPAPER = 0x0014;//设置桌面图片参数
        private const int SPIF_UPDATEINIFILE = 0x01;//更新配置文件
        private const int SPIF_SENDCHANGE = 0x02;//发送改变                                                 
        private const int SPI_GETDESKWALLPAPER = 0x0073;// 获取壁纸文件路径

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);

        [DllImport("user32.dll")] //导入user32.dll函数库
        private static extern bool GetCursorPos(out Point lpPoint);//获取鼠标坐标

        /// <summary>
        /// 设置为桌面壁纸
        /// </summary>
        /// <param name="imagePath">图片路径</param>
        private static void SetWallpaper(string imagePath)
        {
            SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, imagePath, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
        }

        /// <summary>
        /// 设置壁纸样式
        /// </summary>
        /// <param name="style">壁纸样式:Fill（填充）; Fit（适应）; Span（跨屏）; Stretch（拉伸）</param>
        private static void SetWallpaperStyle(string style)
        {
            RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", true);
            if (style.Equals("Fill"))
            {
                key.SetValue("WallpaperStyle", "10");
                key.SetValue("TileWallpaper", "0");
            }
            else if (style.Equals("Fit"))
            {
                key.SetValue("WallpaperStyle", "6");
                key.SetValue("TileWallpaper", "0");
            }
            else if (style.Equals("Span"))
            {
                key.SetValue("WallpaperStyle", "22");
                key.SetValue("TileWallpaper", "0");
            }
            else if (style.Equals("Stretch"))
            {
                key.SetValue("WallpaperStyle", "2");
                key.SetValue("TileWallpaper", "0");
            }
            key.Close();

            // 刷新桌面
            SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, null, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
        }

        /// <summary>
        /// 设置平铺壁纸属性
        /// </summary>
        /// <param name="isTile">平铺壁纸属性:True（是）; False（否）</param>
        private static void SetTileWallpaper(bool isTile)
        {
            RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", true);
            if (isTile)
            {
                key.SetValue("TileWallpaper", "1");
            }
            else
            {
                key.SetValue("TileWallpaper", "0");
            }
            key.Close();

            // 刷新桌面
            SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, null, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
        }

        [DllImport("user32.dll")]
        private static extern IntPtr GetDC(IntPtr hwnd);

        [DllImport("gdi32.dll")]
        private static extern uint GetPixel(IntPtr hdc, int x, int y);

        [DllImport("user32.dll")]
        private static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);

        /// <summary>
        /// 切换到窗口并把窗口设入前台,类似 SetForegroundWindow方法的功能
        /// </summary>
        /// <param name="hWnd">窗口句柄</param>
        /// <param name="fAltTab">True代表窗口正在通过Alt/Ctrl +Tab被切换</param>
        [DllImport("User32.dll")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);

        /// <summary>
        ///  设置窗口的显示状态
        ///  非托管定义为：http://msdn.microsoft.com/en-us/library/windows/desktop/ms633548(v=vs.85).aspx
        /// </summary>
        /// <param name = "hWnd" > 窗口句柄 </ param >
        /// < param name="cmdShow">指示窗口如何被显示</param>
        /// <returns>如果窗体之前是可见，返回值为非零；如果窗体之前被隐藏，返回值为零</returns>
        [DllImport("User32.dll")]
        public static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);

        /// <summary>
        /// 找到某个窗口与给出的类别名和窗口名相同窗口
        /// 非托管定义为：http://msdn.microsoft.com/en-us/library/windows/desktop/ms633499(v=vs.85).aspx
        /// </summary>
        /// <param name="lpClassName">类别名</param>
        /// <param name="lpWindowName">窗口名</param>
        /// <returns>成功找到返回窗口句柄,否则返回null</returns>
        [DllImport("user32.dll")]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

    }

}
